<?php
namespace Menory\Unit\Validation;

use Menory\Standard\IValidator;

class Validator implements IValidator {

    /**
     * @var array
     */
    private $messages = [
        "require"   => "参数不能为空：%field%",
        "minLength" => "参数长度最少为%length%：%field%",
        "maxLength" => "参数长度最多为%length%：%field%",
        "rule"      => "格式不正确",
        "enum"      => "参数：%field%，不在区间内[%enum%]",
    ];

    /**
     * @var array
     */
    private $rules = [];

    /**
     * @var array
     */
    private $data = [];

    /**
     * @param $data
     * @return array
     */
    public function validate($data) {

        if (empty($data)) {
            return [null, new ValidationError("验证数据不能为空")];
        }

        $this->data = $data;

        foreach ($this->rules as $field => $rule) {
            if (!empty($rule)) {
                $actions = explode("|", trim($rule, "|"));
                foreach ($actions as $action) {
                    list($validateMethod, $validateParam) = $this->parseAction($action);
                    if (!method_exists($this, $validateMethod)) {
                        return [null, new ValidationError("不支持的验证方式：" . $validateMethod)];
                    }
                    array_unshift($validateParam, $field);
                    list($this->data, $err) = call_user_func_array([$this, $validateMethod], $validateParam);

                    if ($err !== null) {
                        return [null, $err];
                    }
                }
            }
        }

        return [$this->data, null];

    }

    /**
     * @param array $messages
     * @return void
     */
    function setMessages($messages) {

        $this->messages = array_merge($this->messages, $messages);

    }

    /**
     * @param array $rules
     * @return void
     */
    function setRules($rules) {

        $this->rules = $rules;

    }

    private function parseAction($action) {

        $actions = explode(":", $action, 2);

        return [
            isset($actions[0]) ? "validate" . ucwords($actions[0]) : "validateNotFound",
            isset($actions[1]) ? explode(",", $actions[1]) : []
        ];

    }

    /**
     * 验证是否为空
     * @param $field
     * @return array
     */
    private function validateRequire($field) {

        if (!isset($this->data[$field]) || $this->data[$field] === "") {
            return [null, new ValidationError($this->getMessage($field, "require"))];
        }
        return [$this->data, null];

    }

    /**
     * 验证最小长度
     * @param string $field
     * @param int $length
     * @return array
     */
    private function validateMinLength($field, $length) {

        $currLength = mb_strlen(isset($this->data[$field]) ? $this->data[$field] : "", "utf-8");
        if ($currLength < $length) {
            return [null, new ValidationError($this->getMessage($field, "minLength", ["%length%" => $length]))];
        }
        return [$this->data, null];

    }

    /**
     * 验证最大长度
     * @param string $field
     * @param int $length
     * @return array
     */
    private function validateMaxLength($field, $length) {

        $currLength = mb_strlen(isset($this->data[$field]) ? $this->data[$field] : "", "utf-8");
        if ($currLength > $length) {
            return [null, new ValidationError($this->getMessage($field, "maxLength", ["%length%" => $length]))];
        }
        return [$this->data, null];

    }

    /**
     * 自动处理数据
     * @return array
     */
    public function validateAuto() {

        $functions = func_get_args();
        $field  = array_shift($functions);
        foreach ($functions as $function) {
            if (function_exists($function)) {
                $return = $function($this->data[$field]);
                if ($return === null) {
                    return [null, new ValidationError("该类函数在自动处理数据种不支持：{$function}")];
                }
                $this->data[$field] = $return;
            }
        }
        return [$this->data, null];

    }

    /**
     * 枚举类型验证
     * @return array
     */
    public function validateEnum() {

        $enums = func_get_args();
        $field  = array_shift($enums);
        if (!in_array($this->data[$field], $enums)) {
            return [null, new ValidationError($this->getMessage($field, "enum", ["%enum%" => implode(",", $enums)]))];
        }
        return [$this->data, null];

    }

    /**
     * 验证常用的验证规则
     * @param $field
     * @param $ruleType
     * @return array
     */
    private function validateRule($field, $ruleType) {

        $rule = new ValidationRule();
        list(, $err) = $rule->validate(isset($this->data[$field]) ? $this->data[$field] : "", $ruleType);
        if ($err !== null) {
            return [null, new ValidationError($this->getMessage($field, "rule"))];
        }
        return [$this->data, null];

    }

    /**
     * 获取验证错误信息
     * @param $field
     * @param $messageType
     * @param array $param
     * @return string
     */
    private function getMessage($field, $messageType, $param = []) {

        $message = "validate error";

        if (isset($this->messages[$field . '.' . $messageType])) {
            $message = $this->messages[$field . '.' . $messageType];
        } else if (isset($this->messages[$messageType])) {
            $message = $this->messages[$messageType];
        }

        $param = array_merge(["%field%" => $field], $param);
        return str_replace(array_keys($param), array_values($param), $message);

    }

}